/**********
@name: 图片上传组件
@describtion: 可以选择素材库图片或者本地上传图片作为图片地址
props:
* update:showDialog: 控制显示与关闭弹框
* limit: 限制输出图片张数
emit:
* getImage: 确认选择的回调
@author:liubingye
@date:2023-03-01 09:15:25
***********/
<template>
  <div class="ruifox-image-upload">
    <el-dialog
        v-model="showDialog"
        :append-to-body="isAppendToBody"
        @close="handleClose"
        title="图片上传"
        width="960px"
        class="axupimg-box"
    >
      <div class="inner-axupimg-box">
        <div class="axupimg-upload-box">
          <div class="local-upload">
            <div style="display: inline-flex;margin-left: 10px;">
              <el-button type="primary" style="margin-bottom: 10px" @click="uploadClick">本地上传</el-button>
            </div>
            <el-upload
                ref="uploadRef"
                v-model:file-list="imgUploadList"
                class="upload-demo"
                action=""
                multiple
                :before-upload="handleBeforeUpload"
                :http-request="handleUpload"
                :on-change="handleChangeFiles"
                :show-file-list="false"
                :accept="allow"
                :limit="limit - imgUploadList.length"
                :on-exceed="handleExceed"
                drag
            >
              <template #default>
                <div class="local-upload-list-out">
                  <el-scrollbar height="400px" v-show="imgUploadList.length > 0">
                    <draggable
                        :list="imgUploadList"
                        animation="180"
                        item-key="uid"
                        :force-fallback="true"
                        class="local-upload-list"
                    >
                      <template #item="{ element }">
                        <div>
                          <li>
                            <div class="img-box">
                              <img :src="element.url" alt="">
                            </div>
                            <div class="progress-box" v-show="element.percentage !== 100">
                              <el-progress :percentage="element.percentage" :status="element.status === 'success' ? 'success' : ''" :stroke-width="20"/>
                            </div>
                            <div class="remove-upload" title="删除" @click.stop="removeUpload(element.uid)">
                              <el-icon><Delete /></el-icon>
                            </div>
                          </li>
                          <p class="img-name">{{element.name ? element.name : '网络图片'+element.uid}}</p>
                        </div>
                      </template>
                    </draggable>
                  </el-scrollbar>
                  <div class="no-upload-list" v-show="imgUploadList.length === 0">
                    <p>
                      <i class="iconfont" style="font-size: 48px;margin-bottom: 10px;">&#xe65c;</i><br>
                      暂未上传图片，请点击“本地上传”或拖拽图片到当前区域进行上传
                    </p>
                  </div>
                </div>
              </template>
            </el-upload>
          </div>
        </div>
      </div>
      <template #footer>
          <span class="dialog-footer">
            <el-button type="primary" @click="insertImage" :loading="loadingFiles.length > 0">
              确认
            </el-button>
            <el-button @click="closeDialog">取消</el-button>
          </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {defineProps, defineEmits, ref, watch, reactive} from 'vue';
import {ElMessage} from 'element-plus'
import { uploadCallback } from "@/api/content";
import { Delete } from '@element-plus/icons-vue'
import draggable from "vuedraggable";
import { useStore } from 'vuex';
import {fileMd5, singleUpload, splitUpload} from "@/utils/upload";

const store = useStore()
const props = defineProps({
  //打开dialog
  showDialog: {
    type: Boolean,
    default: false
  },
  limit: {
    type: Number,
    // default: 15
  },
  allow: {
    type: String,
    // default: 'image/png, image/jpeg'
  },
  sizeLimit:{
    type: [String, Number],
  },
  isAppendToBody:{
    type: Boolean,
    default: false
  },
  isToJpg: {
    type: Boolean,
    default: false
  }
})
const showDialog = ref(props.showDialog)
// const limit = ref(props.limit)

const isToJpg = ref(props.isToJpg ? 1 : 0)
watch(props,(newVal) => {
  showDialog.value = newVal.showDialog
},{deep: true})
const emit = defineEmits(['update:showDialog','getImage'])
const handleClose = () => {
  uploadRef.value.clearFiles()
  emit('update:showDialog', false)
}
const closeDialog = () => {
  emit('update:showDialog', false)
}
// 图片上传
const actionUrl = ref(store.state.content.uploadUrl)
const sizeLimit = ref(0)
const limit = ref(0)
const allow = ref(null)
store.dispatch('content/updateUploadUrl',isToJpg.value).then(res => {
  actionUrl.value = res.uploadUrl
  sizeLimit.value = Number(props.sizeLimit || res.size)
  limit.value = props.limit || res.len
  allow.value = props.allow || (res.ext ? res.ext.split('|').map(item=>'.' + item).join(',') : '')
})
const choseImagesList = ref([])
const imgUploadList = ref([])
const uploadRef = ref()

const valid = ref('')
// 上传列表
const loadingFiles = reactive([])
const handleBeforeUpload = async (file) => {
  //限制文件上传类型
  if (allow.value.indexOf(file.type.split('/')[1]) == -1) {
    ElMessage({
      showClose: true,
      message: `文件类型只能是${allow.value}格式!`,
      type: "warning",
    })
    return false
  }
  const limitPass = file.size  < sizeLimit.value;

  //限制文件上传大小
  if (!limitPass) {
    ElMessage({
      showClose: true,
      message: `文件大小不能超过 ${getSizeText(sizeLimit.value)}!，当前${getSizeText(file.size)}`,
      type: "warning",
    })
    return false
  }
  loadingFiles.push(file.uid)
  let res = await fileMd5(file,actionUrl.value)
  if(res.data.length === 0){
    valid.value = res.valid
    return true
  }else{
    loadingFiles.splice(loadingFiles.indexOf(file.uid),1)
    let query = res.data
    query.size = file.size
    query.valid = res.valid
    uploadCallback(query)
    imgUploadList.value.push({
      uid: file.uid,
      percentage: 100,
      url: res.data.url,
      name: file.name,
      status: 'success'
    })

    return false
  }
};
const getSizeText = (size) => {
  if(size > 0 && size / 1024 / 1024 < 1){
    return Math.floor(size / 1024)  + 'Kb'
  }else if(size / 1024 / 1024 >= 1){
    return Math.floor(size / 1024 / 1024) + 'MB'
  }else{
    return size + 'b'
  }
}
const handleExceed = (files) => {
  if(process.env.NODE_ENV === 'development') console.log(files)
  ElMessage({
    showClose: true,
    message: '当前只允许上传'+limit.value+'张图片',
    type: 'warning'
  })
}
// 资源库切换

// const changeLibrary = (id) => {
//   thisLib.value = id
//   getMaterial({id}).then(res => {
//     materialImages.value = res.data
//   })
// }

const handleChangeFiles = (file) => {
  let URL = null;
  if (window.createObjectURL != undefined) {
    // basic
    URL = window.createObjectURL(file.raw);
  } else if (window.URL != undefined) {
    // mozilla(firefox)
    URL = window.URL.createObjectURL(file.raw);
  } else if (window.webkitURL != undefined) {
    // webkit or chrome
    URL = window.webkitURL.createObjectURL(file.raw);
  }
  file.url = URL
}
const handleUpload = async (option) => {
  let _valid = valid.value
  if (option.file.size > 5 * 1024 *1024) {
    let res = await splitUpload(option.file, actionUrl.value ,option.onProgress , 5 * 1024 * 1024)
    handleUploadSuccess(res,option.file,_valid)
  } else {
    // 不切片
    let data = new FormData()
    data.append('file', option.file)
    data.append('name', option.file.name)
    data.append('size', option.file.size)
    data.append('lastModifiedDate', option.file.lastModifiedDate)

    let res = await singleUpload(data, actionUrl.value, option.onProgress)
    handleUploadSuccess(res,option.file,_valid)
  }
}
const handleUploadSuccess = (res,file,valid) => {
  loadingFiles.splice(loadingFiles.indexOf(file.uid),1)
  file.thumb = res.url
  file.id = file.uid
  let query = res
  query.size = file.size
  query.valid = valid
  uploadCallback(query)
}
const removeUpload = (id) => {
  imgUploadList.value = imgUploadList.value.filter(item => item.uid !== id)
}
const insertImage = () => {
  let _imgList = imgUploadList.value.map(item => {
    let _item = {
      id: item.id,
      url: item.url,
      name: item.name
    }
    if(item.uid) {_item.id = item.uid}
    if(item.raw) {_item.id = item.raw.uid;_item.url = item.raw.thumb;_item.name=item.raw.name}
    return _item
  })
  uploadRef.value.clearFiles()
  emit('getImage',_imgList)
  choseImagesList.value = []
  emit('update:showDialog',false)
}
const uploadClick = () => {
  let dom = document.querySelector('.is-drag')
  dom.click()
}
function base64ToBlob (base64, type) {
  const binStr = atob(base64.split(",")[1])
  const len = binStr.length
  const arr = new Uint8Array(len)
  for (let i = 0; i < len; i++) {
    arr[i] = binStr.charCodeAt(i)
  }
  return new Blob([arr], { type })
}
// 接受图文编辑器传来的图片并替换
function messageImgUpload(event) {
  if(event.data?.urlList?.length){
    let base64 = event.data.urlList[0].url
    let imgId = event.data.urlList[0].imgId
    const blob = base64ToBlob(base64, "image/png")
    let data = new FormData()
    data.append('file', blob)
    data.append('name', `${new Date().getTime()}.png`)
    data.append('size', blob.size)
    singleUpload(data, actionUrl.value).then(res=>{
      let imgObj = imgUploadList.value.find(item => item.id == imgId)
      imgObj.url = res.url
    })
  }
}
window.addEventListener('message', function(event) {
  if(event.data.method === 'messageImgUpload'){
    messageImgUpload(event)
  }
});
</script>

<style scoped lang="scss">
::v-deep(.axupimg-box .el-dialog__body){
  padding: 0;
}
::v-deep(.el-tabs--top .el-tabs__item.is-top:nth-child(2)){
  padding-left: 20px;
}
.axupimg-box{
  .inner-axupimg-box{
    display: flex;
    height: 480px;
    .axupimg-upload-box{
      height: 100%;
      width: 100%;
      .local-upload{
        padding: 20px;
        .local-upload-list-out{
          height: 400px;
          .no-upload-list{
            height: 100%;
            width: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            i{
              color: $mainColor;
            }
            p{
              color: #AAAAAA;
              font-size: 14px;
            }
          }
        }
        .local-upload-list{
          height: 400px;
          display: flex;
          flex-wrap: wrap;
          position: relative;
          align-content: flex-start;
          &>div{
            height: 160px;
            width: 160px;
            margin-right: 20px;
            margin-top: 20px;
            background-color: #F8F8F8;
          }
          .img-name{
            font-size: 12px;
            @include textEllipsis(24px,1);
            color: #000;
            text-align: center;
          }
          &>div:nth-child(5n+1){
            margin-left: 18px;
          }
          li{
            transition: all 0.3s;
            height: 160px;
            width: 160px;
            box-sizing: border-box;
            list-style: none;
            border: 1px solid #E4E4E4;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            cursor: pointer;
            .img-box{
              height: 158px;
              width: 158px;
              display: flex;
              justify-content: center;
              align-items: center;
              img{
                max-width: 158px;
                max-height: 158px;
              }
            }
            .progress-box{
              width: 100%;
              position: absolute;
              bottom: 0;
              ::v-deep(.el-progress-bar__outer){
                border-radius: 0;
              }
              ::v-deep(.el-progress-bar__inner){
                border-radius: 0;
              }
            }
            .remove-upload, .online-image-edit{
              color: $white;
              position: absolute;
              right: 5px;
              top: 5px;
              cursor: pointer;
              display: none;
              height: 24px;
              width: 24px;
              background-color: #FF5240;
              box-sizing: border-box;
              border: 1px solid rgba(255,255,255,0.5);
              align-items: center;
              justify-content: center;
              i{
                font-size: 16px;
              }
            }
            &:hover{
              box-shadow: 0 0 10px rgba(0,0,0,0.2);
              border-color: $mainColor;
              background-color: $focusContent;
              .remove-upload, .online-image-edit{
                display: flex;
              }
            }
            .online-image-edit{
              right: 40px;
              background: #fff;
              i{
                font-size: 24px;
                color: $mainColor;
              }
            }
          }
        }
      }
      .online-upload{
        padding: 20px;
        .material-choose-box{
          display: flex;
          margin-bottom: 10px;
          .btn{
            padding: 0 15px;
            line-height: 32px;
            height: 32px;
            border-radius: 100px;
            margin-right: 10px;
            cursor: pointer;
            border: 1px solid #C4C9D5;
          }
          .btn.is-active{
            background-color: $mainColor;
            border-color: $mainColor;
            color: $white;
          }
        }
        .online-upload-list-outer{
          height: 425px;
          width: 100%;
          border: 1px solid $borderColor;
        }
        .online-upload-list{
          display: flex;
          flex-wrap: wrap;
          height: 375px;
          .online-upload-item{
            border: 1px solid #E4E4E4;
            height: 160px;width: 160px;
            background-color: $backBase;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-right: 20px;
            margin-top: 20px;
            cursor: pointer;
            box-sizing: border-box;
            transition: all 0.3s;
            position: relative;
            .upload-item-checkbox{
              position: absolute;
              height: 24px;
              width: 24px;
              box-sizing: border-box;
              border: 1px solid #DCDFE6;
              top: 5px;
              left: 5px;
              background-color: $white;
              display: none;
              transition: all 0.2s;
              align-items: center;
              justify-content: center;
              i{
                font-weight: bold;
                font-size: 18px;
                color: $white;
              }
            }
            img{
              max-width: 100%;
              max-height: 100%;
            }
            &:nth-child(5n+1){
              margin-left: 20px;
            }
            &.is-choose{
              .upload-item-checkbox{
                display: flex;
                background-color: #2CBF77;
                border-color: #2CBF77;
              }
            }
            &:hover{
              background-color: $focusContent;
              border-color: $hoverColor;
              box-shadow: 0 0 10px rgba(0,0,0,0.2);
              .upload-item-checkbox{
                display: flex;
              }
            }
          }
        }
        .chose-img{
          margin-top: 25px;
          .chose-img-title{
            display: flex;
            justify-content: space-between;
            margin-bottom: 10px;
            p{
              span{
                color: #2CBF77;
              }
            }
          }
          .material-chose-list{
            height: 120px;
            background-color: $focusContent;
            padding: 0 40px;
            .inner-material-chose-list{
              display: flex;
              align-items: center;
              height: 120px;
              width: 100%;
              .material-chose-list-item{
                transition: all 0.2s;
                height: 96px;width: 96px;
                position: relative;
                display: flex;
                align-items: center;
                justify-content: center;
                background-color: $backBase;
                border: 1px solid #E4E4E4;
                flex-shrink: 0;
                margin-right: 10px;
                img{
                  max-height: 100%;max-width: 100%;
                }
                .remove-btn{
                  color: $white;
                  position: absolute;
                  right: 5px;
                  top: 5px;
                  cursor: pointer;
                  display: none;
                  height: 24px;
                  width: 24px;
                  background-color: #FF5240;
                  box-sizing: border-box;
                  border: 1px solid rgba(255,255,255,0.5);
                  align-items: center;
                  justify-content: center;
                  i{
                    font-size: 16px;
                  }
                }
                &:hover{
                  background-color: $focusContent;
                  border-color: $hoverColor;
                  box-shadow: 0 0 10px rgba(0,0,0,0.2);
                  .remove-btn{
                    display: flex;
                  }
                }
                &:nth-last-child(1){
                  margin-right: 0;
                }
              }
            }
          }
        }
      }
      .inter-upload{
        padding: 20px;
        p.inter-upload-tips{
          margin-bottom: 20px;
          font-size: 14px;
          color: #333333;
        }
        .inter-upload-list{
          .inter-upload-list-title{
            height: 54px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            color: #333333;
            .title-left{
              font-size: 16px;
            }
            .title-right{
              font-size: 14px;
              span.primary-num{
                color: $mainColor;
              }
            }
          }
          .inner-inter-upload-list{
            border: 1px solid #E4E4E4;
            li{
              height: 60px;
              box-sizing: border-box;
              display: flex;
              align-items: center;
              padding: 0 20px 0 10px;
              &+li{
                border-top: 1px solid #E4E4E4;
              }
              .image-box{
                height: 40px;
                width: 70px;
                display: flex;
                align-items: center;
                justify-content: center;
                background-color: #F2F2F2;
                margin-right: 10px;
                img{
                  max-width: 100%;
                  max-height: 100%;
                }
              }
              p.url{
                flex: 1;
                font-size: 14px;
                @include textEllipsis(18px,1);
              }
              p.url-warning{
                color: $warningColor;
              }
              .success,.warning{
                font-size: 18px;
                margin-right: 10px;
              }
              .success{
                color: $successColor;
              }
              .warning{
                color: $warningColor;
              }
              .delete-btn{
                display: flex;
                height: 24px;
                width: 24px;
                align-items: center;
                justify-content: center;
                color: #ffffff;
                border-radius: 2px;
                background-color: rgba(#333,0.5);
                &:hover{
                  background-color: $failColor;
                }
              }
            }
          }
        }
      }
    }
  }
}
.list-move, /* 对移动中的元素应用的过渡 */
.list-enter-active{
  transition: all 0.5s ease;
}

.list-enter-from,
.list-leave-to {
  opacity: 0;
}

/* 确保将离开的元素从布局流中删除
  以便能够正确地计算移动的动画。 */
.list-leave-active {
  transition: opacity 0.5s ease;
  height: 0!important;width: 0!important;
  margin: 0!important;
}
::v-deep(.el-upload-dragger){
  padding-top: 0;
  padding-bottom: 0;
}
</style>
